﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using XemlUtilities.ISA.Ontology;
using XemlUtilities.DataSet;

namespace XemlUtilities.ISA
{
    public abstract class IsaTable : DataTable
    {
        #region constructors
        public IsaTable(XemlDataSet xds)
            : base()
        {
            sampleIdCol = new DataColumn("id", typeof(int));
            sampleIdCol.AllowDBNull = false;
            this.Columns.Add(sampleIdCol);
            this.PrimaryKey = new DataColumn[] { sampleIdCol };

            foreach (var item in xds.SampleMapping.GetChromatograms().OrderBy(x=>x.SampleRowParent.Id))
            {
                this.Rows.Add(item.FK_Sample);
            }
        }
        #endregion constructors

        private const string TermSourceREF = "Term Source REF";
        private const string TermAccessionNumber = "Term Accession Number";
        private const string Unit = "Unit";
        private const string ProtocolREF = "Protocol REF";

        protected DataColumn sampleIdCol;

        public IEnumerable<DataColumn> GetColumns()
        {
            return this.Columns.Cast<DataColumn>();
        }

        public void Write(System.IO.Stream s)
        {
            System.IO.StreamWriter txtWriter = new System.IO.StreamWriter(s);
            txtWriter.WriteLine(string.Join(IsaExporter.multipleFieldDelimiter, IsaExporter.Encapsulate(this.GetColumns().Skip(1).Select(x => x.Caption).Select(c => c.ToString()).ToList())));
            foreach (DataRow r in this.Rows)
            {
                int sample = GetSampleId(r);
                txtWriter.WriteLine(string.Join(IsaExporter.multipleFieldDelimiter, IsaExporter.Encapsulate(r.ItemArray.Skip(1).Select(c => c.ToString()).ToList())));
            }
            txtWriter.Flush();
        }

        internal DataColumn CreateTermSourceREF()
        {
            DataColumn res = new DataColumn(string.Concat(TermSourceREF, this.GetColumns().Count(x => x.Caption == TermSourceREF)), typeof(string));
            res.Caption = TermSourceREF;
            return res;
        }

        internal DataColumn CreateTermAccessionNumber()
        {
            DataColumn res = new DataColumn(string.Concat(TermAccessionNumber, this.GetColumns().Count(x => x.Caption == TermAccessionNumber)), typeof(string));
            res.Caption = TermAccessionNumber;
            return res;
        }

        internal DataColumn CreateUnit()
        {
            DataColumn res = new DataColumn(string.Concat(Unit, this.GetColumns().Count(x => x.Caption == Unit)), typeof(string));
            res.Caption = Unit;
            return res;
        }

        private DataColumn AddProtocolRefColumn()
        {
            DataColumn res = new DataColumn(string.Concat(ProtocolREF, this.GetColumns().Count(x => x.Caption == ProtocolREF)), typeof(string));
            res.Caption = ProtocolREF;
            return res;
        }

        internal DataColumn AddProtocolRefColumn(string value)
        {
            DataColumn res = Columns.Add(string.Concat(ProtocolREF, this.GetColumns().Count(x => x.Caption == ProtocolREF)), typeof(string));
            res.Caption = ProtocolREF;
            foreach (DataRow sample in this.Rows)
            {
                sample[res] = value;
            }
            return res;
        }

        private const string ParameterValueColumnTemplate = "Parameter Value[{0}]";
        protected DataColumn AddParameterValueColumn(string header, string value)
        {
            String caption = string.Format(ParameterValueColumnTemplate, header); // make the caption
            header = string.Concat(caption, this.GetColumns().Count(x => x.Caption == caption)); // make the caption unique, call it a header ;)
            DataColumn dc = this.Columns.Add(header, typeof(string));
            dc.Caption = caption;

            // fill it with values
            if (!string.IsNullOrEmpty(value))
            {
                foreach (DataRow sample in this.Rows)
                {
                    sample[dc] = value;
                }
            }
            return dc;
        }

        protected DataColumn AddTermSourceREFColumn(string value)
        {
            String header = string.Concat(TermSourceREF, this.GetColumns().Count(x => x.Caption == TermSourceREF));
            DataColumn dc = this.Columns.Add(header, typeof(string));
            dc.Caption = TermSourceREF;
            if (!string.IsNullOrEmpty(value))
            {
                foreach (DataRow sample in this.Rows)
                {
                    sample[dc] = value;
                }
            }
            return dc;
        }

        protected DataColumn AddTermAccessionNumberColumn(string value)
        {
            String header = string.Concat(TermAccessionNumber, this.GetColumns().Count(x => x.Caption == TermAccessionNumber));
            DataColumn dc = this.Columns.Add(header, typeof(string));
            dc.Caption = TermAccessionNumber;
            if (!string.IsNullOrEmpty(value))
            {
                foreach (DataRow sample in this.Rows)
                {
                    sample[dc] = value;
                }
            }
            return dc;
        }

        protected DataColumn AddColumn(string header, string value)
        {
            DataColumn dc = this.Columns.Add(header, typeof(string));
            if (!string.IsNullOrEmpty(value))
            {
                foreach (DataRow sample in this.Rows)
                {
                    sample[dc] = value;
                }
            }
            return dc;
        }

        internal int GetSampleId(DataRow samplerow)
        {
            return samplerow.Field<int>(sampleIdCol);
        }

        public String escape(String input)
        {
            return input.Replace("=>", ">");
        }
    }
}
